#!/usr/bin/python3
# -*- coding: utf-8 -*-


import os
import sys

from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QIcon, QPainter, QFont, QFontMetrics, QPalette, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QFrame, QGridLayout, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QToolTip, QWidget, qApp, QDesktopWidget, QPushButton

from replace import BRACKETS

BASE_DIR = os.path.dirname(os.path.realpath(__file__))
BOOK_DIR = os.path.join(BASE_DIR, 'books')


class BookHelp(QDialog):
    HELP = [
        ('←、↓、↲、&lt;PgDn&gt;、&lt;鼠标左键&gt;', '向右翻页'),
        ('→、↑、&lt;PgUp&gt;、&lt;鼠标右键&gt;', '向左翻页'),
        ('&lt;Esc&gt;', '返回主界面'),
        ('0、&lt;Ins&gt;', '翻到第1页'),
        ('+、-', '放大、缩小字体'),
    ]

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 320, 220)
        self.center()
        self.setWindowTitle("竖版阅读帮助")

        grid = QGridLayout()
        self.setLayout(grid)
        i = 0

        for key, value in self.HELP:
            grid.addWidget(QLabel(key, self), i, 0)
            lbl = QLabel(value, self)
            lbl.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
            grid.addWidget(lbl, i, 1)
            i += 1

        btn = QPushButton('退出')
        btn.clicked.connect(self.close)
        grid.addWidget(btn, i, 1)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


class PeBook(QDialog):
    def __init__(self, filename, fontsize=28):
        super().__init__()
        self.fontsize = fontsize
        self.initUI()
        self.reloadBook(filename)

    def reloadBook(self, book, lineIndex=[(0, 0), ]):
        self.lineIndex = lineIndex
        # 设置页边距
        self.margin = 16
        self.setFont()
        # 读取内容
        self.readBook(os.path.join(BOOK_DIR, book))

    def setFont(self):
        # 设置字体
        self.font = QFont('ubuntu', self.fontsize)
        fsize = QFontMetrics(self.font)
        # 计算文字宽度
        self.lineWidth = int(fsize.width('经') * 1.5)
        # 计算文字高度
        self.charHeight = int(fsize.height() * 1.2)

    def initUI(self):
        # 窗体显示最大化
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.desktopRect = QApplication.desktop()
        # 设置背景色
        pe = QPalette()
        pe.setColor(self.backgroundRole(), QColor(255, 255, 204, 153))
        self.setPalette(pe)
        self.setAutoFillBackground(True)
        self.setGeometry(0, 0, self.desktopRect.width(), self.desktopRect.height())

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        self.drawLines(painter)
        painter.end()

    def mousePressEvent(self, event):
        # 鼠标点击事件，左键向前翻面，右键向后翻页
        if event.button() == Qt.LeftButton:
            # 向前翻页
            self.repaint()
        elif event.button() == Qt.RightButton:
            # 向后翻页
            if len(self.lineIndex) > 2:
                self.lineIndex = self.lineIndex[:-2]
                self.repaint()

    def keyPressEvent(self, event):
        key = event.key()
        # 向右翻页
        if key == Qt.Key_Right or key == Qt.Key_Up or key == Qt.Key_PageUp:
            if len(self.lineIndex) > 2:
                self.lineIndex = self.lineIndex[:-2]
                self.repaint()
        # 向左翻页
        elif key == Qt.Key_Left or key == Qt.Key_Down or key == Qt.Key_PageDown or key == Qt.Key_Enter:
            self.repaint()
        # 退出阅读页面
        elif key == Qt.Key_Escape:
            self.close()
        # 回到第一页
        elif key == Qt.Key_0 or key == Qt.Key_Insert:
            self.lineIndex = [(0, 0), ]
            self.repaint()
        # 放大显示字体
        elif key == Qt.Key_Plus:
            self.fontsize += 1
            self.fontsize = self.fontsize if self.fontsize < 60 else 60
            self.setFont()
            self.repaint()
        # 缩小显示字体
        elif key == Qt.Key_Minus:
            self.fontsize -= 1
            self.fontsize = self.fontsize if self.fontsize > 16 else 16
            self.setFont()
            self.repaint()

    def drawLines(self, painter):
        painter.setFont(self.font)

        # 右边起始
        right = self.width() - self.margin
        # 顶端起始
        top = self.margin
        # 底部结束
        bottom = self.height() - self.margin

        self.setWindowTitle(self.title)
        # 从右边开始显示文字
        x = right
        xr = x
        # 下一行索引 next line index
        nli = self.lineIndex[-1][0]
        # 当前行下一字索引 next char index
        nci = self.lineIndex[-1][1]
        # 标记本页是否已经写完
        page_full = False
        # 从下一行索引开始，到结束行为止，依次写字
        for i in range(self.lineIndex[-1][0], len(self.lines)):
            # 下一行索引加1
            nli += 1
            # 从顶部开始写
            y = top
            # 重置当前行待写字索引
            j = nci
            # 在当前行右边竖线
            painter.drawLine(x, top, x, bottom)
            # 从当前行下一字开始，依次写字
            for s in self.lines[i][nci:]:
                # 待写字索引加1
                j += 1
                # 替换横写标点为纵写标点
                if s in BRACKETS[1].keys():
                    s = BRACKETS[1][s]
                # 计算待写字位置区域
                rect = QRect(x - self.lineWidth, y, self.lineWidth, self.charHeight)
                # 写字到位置区域
                painter.drawText(rect, Qt.AlignCenter, s)
                # 纵坐标下移
                y += self.charHeight
                # 判断纵坐标是否超过底部，以及本行是否已经写完，这两种情况，都要换行
                if rect.bottom() + self.charHeight > bottom and j < len(self.lines[i]):
                    # 纵坐标重置到顶部
                    y = top
                    # 横坐标向左移一列
                    x -= self.lineWidth
                    # 画行内左边竖线
                    painter.drawLine(x, top, x, bottom)
                    # 判断下一行是否已经超出本页左限位
                    if x - self.lineWidth <= self.margin:
                        # 如果超出，因为本行还未完成，故下一页继续从当前行开始
                        nli -= 1
                        # 下一页从本行下一字符开始
                        nci = j
                        # 标记页面已满，然后退出本循环（行的循环也要退出，故此需要页面已满标记
                        page_full = True
                        break
            if not page_full:
                # 如果不是因为上一行写字未满页面已经满的情况，下一字应该下一行首字符开始
                nci = 0
            # 计算下一行横坐标起始位置
            x -= self.lineWidth
            # 判断下一行起始位置加上下一行宽度超出本页面，或者页面标记已满
            if x - self.lineWidth <= self.margin or page_full:
                # 画左边竖线
                painter.drawLine(x, top, x, bottom)
                break
        # 判断所有行是否已经写入完毕
        if nli < len(self.lines):
            # 记录下一行和下一字位置
            self.lineIndex.append((nli, nci))
        else:
            # 画右边竖线
            painter.drawLine(x, top, x, bottom)

        if page_full:
            # 如果本行还未结束，页面已满，行间换行不需要，所以要去除行间换行
            x += self.lineWidth
        # 画顶部横线
        painter.drawLine(x, top, xr, top)
        # 画底部横线
        painter.drawLine(x, bottom, xr, bottom)

    def readBook(self, filename):
        # 以文件名作为本页标题
        self.title = os.path.basename(filename).split('.')[0]
        # 按行读取本书
        self.lines = []
        with open(filename, 'r') as file:
            for line in file.readlines():
                self.lines.append(line.rstrip())


class BookFrame(QFrame):
    def __init__(self, fileName):
        super().__init__()
        self.fileName = fileName
        self.initUI()

    def initUI(self):
        vbox = QVBoxLayout()
        self.setLayout(vbox)
        self.resize(300, 400)

        font = QFont('ubuntu', 16)
        label = QLabel(self)
        label.setFont(font)
        label.setAlignment(Qt.AlignCenter)
        label.setText(self.fileName.split('.')[0])
        vbox.addWidget(label)

        if self.fileName:
            pe = QPalette()
            pe.setColor(self.backgroundRole(), QColor(0, 51, 102))
            pe.setColor(self.foregroundRole(), QColor(255, 204, 153))
            self.setPalette(pe)
            self.setAutoFillBackground(True)
            self.setFrameStyle(QFrame.Panel | QFrame.Raised)
            self.book = PeBook(self.fileName)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.showMe()

    def showMe(self):
        if self.fileName:
            self.book.show()


class BookManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.lineLength = 9
        self.rowLength = 4
        self.initUI()

    def initUI(self):
        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)

        QToolTip.setFont(QFont('ubuntu', 10))
        self.setToolTip("按 <b>F1</b> 查看帮助")
        self.setWindowTitle('Portrait E Book')
        self.desktopRect = QApplication.desktop()
        self.setGeometry(0, 0, self.desktopRect.width(), self.desktopRect.height())

        # 设置图标
        self.icon = QIcon(os.path.join(BASE_DIR, 'book.svg'))
        self.setWindowIcon(self.icon)
        self.setWindowIconText("Portrait E Book")

        grid = QGridLayout()
        grid.setHorizontalSpacing(self.lineLength)
        grid.setVerticalSpacing(self.rowLength)
        centralWidget.setLayout(grid)

        i = 0
        for file in os.listdir(BOOK_DIR):
            fm = BookFrame(file)
            # fm.setFixedSize(190, 240)
            grid.addWidget(fm, i // self.lineLength, i % self.lineLength)
            i += 1

        if i < self.lineLength * self.rowLength:
            for j in range(i, self.lineLength * self.rowLength):
                fm = BookFrame('')
                # fm.setFixedSize(190, 240)
                grid.addWidget(fm, i // self.lineLength, i % self.lineLength)
                i += 1

        self.show()

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_F1:
            self.hp = BookHelp()
            self.hp.show()
        elif key == Qt.Key_Escape:
            qApp.quit()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    bm = BookManager()
    sys.exit(app.exec_())
